﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Sunny.Lib
{
    public class PollWaitUtility
    {
        //Function to encapsulate polling condition.  
        public delegate bool PollCondition();
        private static readonly TimeSpan defaultRetryInterval = TimeSpan.FromSeconds(1);
        private static readonly TimeSpan defaultTimeout = TimeSpan.FromMinutes(1);
        public static bool PollWait(PollCondition conditionDelegate)
        {
            //Default retry interval - 1s  
            return PollWait(conditionDelegate, defaultRetryInterval);
        }

        public static bool PollWait(PollCondition conditionDelegate, TimeSpan retryInterval)
        {
            //Default timeout - 60s  
            return PollWait(conditionDelegate, retryInterval, defaultTimeout);
        }

        /// <summary>  
        /// Sleeps the current thread until the delegate function returns true, or timeout expires.  
        /// </summary>  
        /// <param name="conditionDelegate">Function that checks polling condition</param>  
        /// <param name="retryInterval">Time to wait between polls.</param>  
        /// <param name="timeout">Maximum amount of time to wait.</param>  
        /// <returns>true if condition is satisfied, false if timeout expires without condition being satisfied.</returns>  
        public static bool PollWait(PollCondition conditionDelegate, TimeSpan retryInterval, TimeSpan timeout)
        {
            Debug.Assert(retryInterval <= timeout,
                string.Format("Retry interval '{0}' is greater than timeout '{1}'", retryInterval, timeout));

            if (conditionDelegate()) return true;

            DateTime waitStartTime = DateTime.Now;
            while (DateTime.Now.Subtract(waitStartTime) < timeout)
            {
                System.Threading.Thread.Sleep(retryInterval);
                if (conditionDelegate()) return true;
            }

            return false;
        }
    }
}
